package com.demo7;

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.arm.backend.Backend;
import com.github.unidbg.arm.backend.EventMemHook;
import com.github.unidbg.arm.backend.UnHook;
import com.github.unidbg.arm.backend.Unicorn2Factory;
import com.github.unidbg.file.linux.AndroidFileIO;
import com.github.unidbg.linux.android.AndroidARMEmulator;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.DalvikModule;
import com.github.unidbg.linux.android.dvm.DvmClass;
import com.github.unidbg.linux.android.dvm.DvmObject;
import com.github.unidbg.linux.android.dvm.VM;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.memory.SvcMemory;
import com.github.unidbg.unix.UnixSyscallHandler;
import com.github.unidbg.virtualmodule.android.AndroidModule;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import unicorn.UnicornConst;

import java.io.File;

public class TongDun{
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;
    private final DvmClass TongdunClazz;

    public TongDun(){
        // 创建模拟器实例
        AndroidEmulatorBuilder builder = new AndroidEmulatorBuilder(false){
            @Override
            public AndroidEmulator build() {
                return new AndroidARMEmulator(processName,rootDir,backendFactories) {
                    @Override
                    protected UnixSyscallHandler<AndroidFileIO> createSyscallHandler(SvcMemory svcMemory) {
                        return new TDARM32SyscallHandler(svcMemory);
                    }
                };
            }
        };

        emulator = builder
                .setProcessName("com.hundsun.qy.hospitalcloud.bj.xhhosp.hsyy")
                .addBackendFactory(new Unicorn2Factory(true))
                .setRootDir(new File("target/rootfs"))
                .build();

        emulator.getSyscallHandler().setEnableThreadDispatcher(false);
        final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口
        memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析

        vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/demo7/apkFiles/crack_v2.20.apk")); // 创建Android虚拟机
        vm.addNotFoundClass("android/telephony/ColorOSTelephonyManager");

        // 虚拟模块 libandroid.so
        new AndroidModule(emulator, vm).register(memory);
        // Hook import functions 模块监听器
        memory.addModuleListener(new hookFuncs(emulator, "libtongdun.so", "src/main/resources/tongdun/functions/imports.txt"));
        // 补JNI
        vm.setJni(new TDJNI(emulator));
        vm.setVerbose(false);

        // 补文件访问
        emulator.getSyscallHandler().addIOResolver(new TDIO());
        vm.setVerbose(true); // 设置是否打印Jni调用细节

        DalvikModule dm = vm.loadLibrary("tongdun", true);
        module = dm.getModule();
        dm.callJNI_OnLoad(emulator);

        TongdunClazz = vm.resolveClass("cn/tongdun/android/shell/HelperJNI");
        CollectorError.remove(CollectorError.TYPE.ERROR_INIT);

        patch();
    }

    public void patch(){
        emulator.getBackend().hook_add_new(new EventMemHook() {
            @Override
            public boolean hook(Backend backend, long address, int size, long value, Object user, UnmappedType unmappedType) {
                return true;
            }

            @Override
            public void onAttach(UnHook unHook) {
            }
            @Override
            public void detach() {
                throw new UnsupportedOperationException();
            }
        }, UnicornConst.UC_HOOK_MEM_READ_UNMAPPED | UnicornConst.UC_HOOK_MEM_WRITE_UNMAPPED | UnicornConst.UC_HOOK_MEM_FETCH_UNMAPPED, null);
    }

    public void init(){
        callTongdun();
    }

    public void callTongdun(){
        String methodSign = "tongdun(Landroid/content/Context;)V";
        TongdunClazz.callStaticJniMethod(emulator,methodSign,vm.resolveClass("android/content/Context").newObject(null));
    }


    public String sign(){
        String methodSign = "XOnEvent(Landroid/content/Context;)Ljava/lang/String;";
        DvmObject<?> ret = TongdunClazz.callStaticJniMethodObject(emulator,methodSign,vm.resolveClass("android/content/Context").newObject(null));
        return ret.getValue().toString();
    }

    public static void main(String[] args) throws InterruptedException {
//        Logger.getLogger("com.github.unidbg.linux.ARM32SyscallHandler").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.linux.MyARM32SyscallHandler").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.unix.UnixSyscallHandler").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.AbstractEmulator").setLevel(Level.INFO);
//        Logger.getLogger("com.github.unidbg.linux.android.dvm.DalvikVM").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.linux.android.dvm.BaseVM").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.linux.android.dvm").setLevel(Level.DEBUG);
//        Logger.getLogger("com.github.unidbg.thread").setLevel(Level.DEBUG);

        TongDun td = new TongDun();
        td.init();
        System.out.println("=============================================================================");
        long b = System.currentTimeMillis();
        String str = td.sign();
        long e = System.currentTimeMillis();
        System.out.println("cost:"+(e-b)+", content:"+str);
//
    }
}
